﻿/**
 * Class: OpenLayers.Layer.PoiLayer
 * POI图层，用于显示POI图层
 *
 * 继承自:
 *  - <OpenLayers.Layer>
 * @requires OpenLayers/Layer/Markers.js
 */
OpenLayers.Layer.PoiLayer = OpenLayers.Class(OpenLayers.Layer.Markers, {
   /**
    * 
    * Parameters:
    * filterByBound - {boolean}是否根据地图范围的变化更新数据
    */
    filterByBounds: false,
    /**
     *	根据poi的类型分类的marker集合
     */
    typemarkers: null,
    /**
     * 根据id缓存marker是否存在
     */
    idmarkers: null,
    /**
     * 不同类型的poi点的lonlat
     */
    typelonlats: null,
    /**
     *
     * Parameters:
     * data - {String}服务器端返回的poi json数据
     */
    data: null,
    /**
     * poi鼠标滑过显示标注信息图层
     */
    labelLayer: null,
    /**
     * 最后选中的marker
     */
    lastSelectedMarker: null,
    /**
     * 上次高亮的poi
     */
    lastHighlightMarker: null,
    /**
     * function
     */
    clickEnd: null,
    
    labelPersist: false,
    
    /**
     * Constructor: OpenLayers.Layer.PoiLayer
     * Create a PoiLayer.
     *
     * Parameters:
     * name - {String}
     * options - {Object} Hashtable of extra options to tag onto the layer
     */
    initialize: function(name, options){
        OpenLayers.Layer.Markers.prototype.initialize.apply(this, arguments);
    },
    
    /**
    * Method: setMap
    * 指定PoiLayer所归属的地图对象，当图层加至地图时触发此方法
    */    
   setMap: function(map) {
        OpenLayers.Layer.prototype.setMap.apply(this, arguments); 
        //监听moveend事件
        if(this.filterByBounds){
            this.registerUpdateEvent();
        }else{
            //如果实时过滤为false.则一次加载地图最大范围内的poi
            this.createPois(this.map.getMaxExtent());
        }
        //添加标注图层
        this.labelLayer = new OpenLayers.Layer.Labels("poi_labelLayer");
        this.map.addLayer(this.labelLayer);
        var poiindex = map.Z_INDEX_BASE["Popup"];
        this.setZIndex(poiindex);
        this.labelLayer.setZIndex(poiindex+1);
	 
        this.div.style.cursor = "pointer";
   },
	
   /**
    * 设置地图更新事件
    *
    */
    registerUpdateEvent: function(){
        this.map.events.register("moveend", this, this.redrawByBounds);
    },
   
    /**
    * 地图范围发生变化后的
    *
    */
    redrawByBounds: function(){
        if(this.visibility){
            this.createPois(this.map.getExtent());
        }
   },
    
    /**
     * 服务器端获取poi json数据返回
     *
     */
    getPoiData: null,
    
    /**
     *服务器端poi数据返回后构建marker数组，并设置marker鼠标事件
     *
     */
    createPois: function(bounds){
        //如果filterByBounds为true,则在zoomend事件触发createPois函数清除上一视图的pois
        if(this.filterByBounds){
            this.clearPoiMarkers();
        }
        this.initCacheData();

		//获取poi数据
		if(this.data){
			this.createMarkers();
		}else{
			var zoom = this.map.getZoom();
			var scope = this;
			this.getPoiData(bounds, zoom, function(data){
				scope.data = data;
				scope.createMarkers();
			});
		}
    },
    
    /**
     * 
     */
    refreshMarkers: function(){},
    
    /**
     * 清除markers
     */
    clearPoiMarkers: function(){
        this.clearMarkers();
        this.typemarkers = null;
        this.typelonlats = null;
        this.idmarkers = null;
        this.initCacheData();
    },
    
    /**
     * 初始化缓存数据
     */
    initCacheData: function(){
        //缓存数据
		this.idmarkers = {};
		this.typemarkers = {};
		this.typelonlats = {};
    },
    
    /**
     * 创建icon对象
     */
    createIcon: function(typedata, cback){
        var align = typedata.align || "center_bottom";
        var img = new Image();
        var scope = this;
        img.onload = function(){
            var size = new OpenLayers.Size(img.width, img.height);
            var offsets = scope.getOffset(img.width, img.height, align);
            var icon = new OpenLayers.Icon(typedata.icon,size,offsets[0]);
            icon.labelOffset = offsets[1];
            if(cback){
                cback.apply(scope, [icon]);
            }
        }
        img.src = typedata.icon;
    },
    
    getOffset: function(w, h, align){
        var offsetx = offsety = 0;
        var labelx = labely = 0;
        switch(align){
            case "top_left":{
                labelx = w;
                break;
            }
            case "top_center":{
                offsetx = -w/2;
                labelx = w/2;
                break;
            }
            case "top_right":{
                offsetx = -w;
                break;
            }
            case "center_left":{
                offsety = -h/2;
                labelx = w;
                labely = -h/2;
                break;
            }
            case "center_center":{
                offsetx = -w/2;
                offsety = -h/2;
                labelx = w/2;
                labely = -h/2;
                break;
            }
            case "center_right":{
                offsetx = -w;
                offsety = -h/2;
                labely = -h/2;
                break;
            }
            case "bottom_left":{
                offsety = -h;
                labelx = w;
                labely = -h;
                break;
            }
            case "bottom_center":{
                offsetx = -w/2;
                offsety = -h;
                labelx = w/2;
                labely = -h;
                break;
            }
            case "bottom_right":{
                offsetx = -w;
                offsety = -h;
                labely = -h;
                break;
            }
        }

        return [new OpenLayers.Pixel(offsetx, offsety), new OpenLayers.Pixel(labelx, labely)];
    },
 	
    /**
     * 根据poi数据创建所有marker
     */
    createMarkers: function() {
        for(var i in this.data){
            var typedata = this.data[i];
            this.createsingleTypeMarkers(typedata, i);
        }
    },
    
    /**
    * 根据poi数据创建所有单个marker,并加入到
    */
   createsingleTypeMarkers: function(typedata, typeName) {
        this.createIcon(typedata, function(poiTypeicon){
        if(this.typemarkers[typeName]==null)
            this.typemarkers[typeName]=[];
        if(this.typelonlats[typeName]==null)
            this.typelonlats[typeName]=[];
        
        //为了提高绘制marker的效率将减少marker注册事件的BROWSER_EVENTS中的事件名称。
        //在创建完了所有的marker之后还原BROWSER_EVENTS。
        OpenLayers.Events.prototype.BROWSER_EVENTS = ["mouseout","mouseover","click"];

            var data = typedata.data;
            for(var j in data){
                var x = data[j].x || data[j].X;
                var y = data[j].y || data[j].Y;
                var lonlat = new OpenLayers.LonLat(x,y);
                
                var marker = this.createMarker(poiTypeicon, typedata.activeIcon, typeName, lonlat, data[j]);
                this.appendMarker(marker);
                
                this.typemarkers[typeName].push(marker);
                this.typelonlats[typeName].push(lonlat);
                this.idmarkers[data[j].id || data[j].ID] = marker;
            }
            
            if(this.labelPersist){
                this.showLabels();
            }
            
            //还原OpenLayers.Events.prototype.BROWSER_EVENTS
            OpenLayers.Events.prototype.BROWSER_EVENTS = [
                "mouseover", "mouseout",
                "mousedown", "mouseup", "mousemove", 
                "click", "dblclick", "rightclick", "dblrightclick",
                "resize", "focus", "blur",
                "touchstart", "touchmove", "touchend",
                "keydown"
            ];
            });
   },
    
    
    /**
     * 添加marker对象
     */
    appendMarker: function(marker){
    	this.addMarker(marker);
    },
    
    /**
     * 创建marker对象
     */
    createMarker: function(icon, activeIcon, typename, lonlat, poidata) {
        var marker = new OpenLayers.Marker(lonlat,icon.clone());
        marker.icon.labelOffset = icon.labelOffset;
        marker.data = poidata;
        marker.defaultIcon = icon.url;
        marker.activeIcon = activeIcon;
        marker.typeName = typename;
        marker.id = poidata.id || poidata.ID;
            var options = {
                poidata: poidata,
                lonlat: lonlat,
                owner: this,
                marker:	marker,
                icon: icon
            };
           //注册鼠标点击和鼠标滑过事件
           marker.events.register('click', options, this.onMouseClick);
           if(!this.labelPersist){
                marker.events.register('mouseover', options, this.onMouseMove);
                marker.events.register('mouseout', options, this.onMouseOut);
           }
           return marker;
    },
    
    showLabels: function(){
        this.labelLayer.clear();
        for(var i in this.markers){
            var marker = this.markers[i];
            if(marker.icon.imageDiv.style.display != "none"){
                var poidata = marker.data;
                //添加标注
            	var title = poidata.title || poidata.TITLE;
            	
            	var label = new OpenLayers.Label(marker.lonlat, title, "poiLabel");
        		label.offset = marker.icon.labelOffset;
            	this.labelLayer.add(label);
            }
        }
    },
    
    persistLabels: function(){
        this.labelPersist = true;
        for(var i in this.markers){
            var marker = this.markers[i];
            marker.events.unregister('mouseover', undefined, this.onMouseMove);
           	marker.events.unregister('mouseout', undefined, this.onMouseOut);
        }
        this.showLabels();
    },
    
    /**
     *响应鼠标滑过事件
     *
     */
    onMouseMove: function(evt){
    	//清除掉标注信息
    	var owner = this.owner;
    	owner.labelLayer.clear();
    	var poidata = this.poidata;
    	
    	//添加标注
    	var title = poidata.title || poidata.TITLE;
    	var label = new OpenLayers.Label(this.marker.lonlat, title, "poiLabel");
		label.offset = this.icon.labelOffset;
    	owner.labelLayer.add(label);
    	
    	//高亮POI
    	if(!owner.isMarkerEqual(this.marker, owner.lastSelectedMarker)){
	    	owner.highlightPOI(this.marker);
	    }
    },
    
    onMouseOut: function() {
    	//清除掉标注信息
    	var owner = this.owner;
    	owner.labelLayer.clear();
		var cursor = this.owner.map.layerContainerDiv.style.cursor;
		this.owner.map.layerContainerDiv.style.cursor = "";
		this.owner.map.layerContainerDiv.style.cursor = cursor;
    	//消除高亮
    	if(!owner.isMarkerEqual(this.marker, owner.lastSelectedMarker)
    		&& !owner.isMarkerEqual(owner.lastHighlightMarker, owner.lastSelectedMarker)){
	    	owner.clearHighlight(this.marker);
    	}
    },
    /**
     *响应鼠标点击事件
     *
     */
    onMouseClick: function(evt){
    	var poidata = this.poidata;
    	var owner = this.owner;
    	
		//高亮POI
		if(!owner.isMarkerEqual(this.marker, owner.lastSelectedMarker)){
			//清除上次点击的poi的高亮状态
			if(owner.lastSelectedMarker != null){
				owner.clearHighlight(owner.lastSelectedMarker);
			}
		    owner.lastSelectedMarker = this.marker;
		    owner.highlightPOI(this.marker);
	    }
	    
	    
	    //clickEnd外部自定义点击响应
	    if(owner.clickEnd != null && typeof owner.clickEnd == "function"){
	    	owner.clickEnd(this);
	    }
    },
    /**
     * 高亮POI
     * 如果当前poi的poiTypeParam中的activateImgURL属性有值则高亮该poi
	 * 先清除上次选中的poi的高亮状态
     */
    highlightPOI: function(currentMarker) {
    	var activeImgUrl = currentMarker.activeIcon;
    	//如果存在高亮图标
    	if(activeImgUrl != null){
	    	if(this.lastHighlightMarker != null && !this.isMarkerEqual(this.lastHighlightMarker, this.lastSelectedMarker)){
	    		this.clearHighlight(this.lastHighlightMarker);
	    	}
	    	currentMarker.setUrl(activeImgUrl);
	    	this.lastHighlightMarker = currentMarker;
	    }
    },
    
    /**
     * 消除高亮
     */
    clearHighlight: function(marker) {
    	if(marker != null){
    		var iconImgURL = marker.defaultIcon;
    		marker.setUrl(iconImgURL);
    	}
    },
    
    /**
     * 判断两个poi是否相同
     */
    isMarkerEqual: function(marker1, marker2) {
    	if(marker1 == null){
    		return false;
    	}
    	if(marker2 == null){
    		return false;
    	}
    	var poitype1 = marker1.typeName;
    	var poitype2 = marker2.typeName;
    	var id1 = marker1.data.id || marker1.data.ID;
    	var id2 = marker2.data.id || marker2.data.ID;
    	
    	//当poi的类型相同，并且poi的id相同则视为两个poi相同。
    	if((poitype1 == poitype2) && (id1 == id2)){
    		return true;
    	}else{
    		return false;
    	}
    },
    /**
     * 显示或隐藏markers
     */
    dispalyMarkers: function(markers, display) {
    	for(var i in markers){
    		if(markers[i].id) {
    			markers[i].icon.display(display);
    		}
    	}
    },
    
    /**
    * 设置关联图层
    */
   connectLayer: function(layer) {
   	layer.events.register("visibilitychanged", {connectLayer:layer,poiLayer:this}, this.visibilityChange);
   },
   
   /**
    * 关联图层可见变化后清除poi
    */
    visibilityChange: function() {
	this.poiLayer.setVisibility(this.connectLayer.visibility);
   	this.poiLayer.clearPoiMarkers();

   },

   removeMap: function(objmap) {
	   objmap.events.unregister("moveend", this, this.redrawByBounds);
	   if(this.labelLayer && this.labelLayer.div){
		   this.map.removeLayer(this.labelLayer);
		   this.labelLayer.destroy();
	   }
   },
   
    CLASS_NAME: "OpenLayers.Layer.PoiLayer"
});



